//package com.zeal.zealsay.security.filter;
//
//import com.zeal.zealsay.common.constant.enums.ResultCode;
//import com.zeal.zealsay.config.FilterIgnorePropertiesConfig;
//import com.zeal.zealsay.exception.ServiceException;
//import com.zeal.zealsay.util.JwtTokenUtil;
//import io.jsonwebtoken.ExpiredJwtException;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
//import org.springframework.security.core.context.SecurityContextHolder;
//import org.springframework.security.core.userdetails.UserDetails;
//import org.springframework.security.core.userdetails.UserDetailsService;
//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
//import org.springframework.stereotype.Component;
//import org.springframework.util.AntPathMatcher;
//import org.springframework.web.filter.OncePerRequestFilter;
//
//import javax.servlet.FilterChain;
//import javax.servlet.ServletException;
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//
//@Slf4j
//@Component
//public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
//
//  @Autowired
//  FilterIgnorePropertiesConfig filterIgnorePropertiesConfig;
//
//  private final UserDetailsService userDetailsService;
//  private final JwtTokenUtil jwtTokenUtil;
//  private final String tokenHeader;
//
//  public JwtAuthorizationTokenFilter(UserDetailsService userDetailsService,
//                                     JwtTokenUtil jwtTokenUtil,
//                                     @Value("${jwt.header}") String tokenHeader) {
//    this.userDetailsService = userDetailsService;
//    this.jwtTokenUtil = jwtTokenUtil;
//    this.tokenHeader = tokenHeader;
//  }
//
//  @Override
//  protected void doFilterInternal(HttpServletRequest request,
//                                  HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
//    log.info("processing authentication for '{}'", request.getRequestURL());
//    boolean access = false;
//    AntPathMatcher pathMatcher = new AntPathMatcher();
//    for (String url : filterIgnorePropertiesConfig.getUrls()) {
//      if (pathMatcher.match(url, request.getRequestURI())) {
//        log.info("this path authentication unnecessary!");
//        access = true;
//      }
//    }
//    if (!access) {
//      final String requestHeader = request.getHeader(this.tokenHeader);
//
//      String username = null;
//      String authToken = null;
//      if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
//        authToken = requestHeader.substring(7);
//        try {
//          username = jwtTokenUtil.getUsernameFromToken(authToken);
//        } catch (IllegalArgumentException e) {
//          log.error("an error occured during getting username from token", e);
//        } catch (ExpiredJwtException e) {
//          log.warn("the token is expired and not valid anymore", e);
//        }
//      } else {
//        log.info("couldn't find bearer string, will ignore the header");
//      }
//
//      log.info("checking authentication for user '{}'", username);
//      if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
//        log.info("security context was null, so authorizating user");
//
//        // It is not compelling necessary to load the use details from the database. You could also store the information
//        // in the token and read it from it. It's up to you ;)
//        UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
//
//        // For simple validation it is completely sufficient to just check the token integrity. You don't have to call
//        // the database compellingly. Again it's up to you ;)
//        if (jwtTokenUtil.validateToken(authToken, userDetails)) {
//          UsernamePasswordAuthenticationToken authentication =
//              new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
//          authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//          log.info("authorizated user '{}', setting security context", username);
//          SecurityContextHolder.getContext().setAuthentication(authentication);
//        }
//      }
//    }
//    chain.doFilter(request, response);
//  }
//
//}
